﻿using CommunityToolkit.Mvvm.Input;
using NPOI.HSSF.Record;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using TlToolBase;
using TlToolBase.Mode;
using TlToolCordCreate.ViewMode;
using TlToolCordCreate.Web;

namespace TlToolCordCreate.Mode
{
    /// <summary>
    /// 表属性
    /// </summary>
    public class TableProperties
    {

        /// <summary>
        /// 表名
        /// </summary>
        public string TableName { get; set; }
        /// <summary>
        /// 表描述
        /// </summary>
        public string TableDescribe { get; set; }
        /// <summary>
        /// 类名
        /// </summary>
        public string ClassName { get; set; }
        /// <summary>
        /// 继承
        /// </summary>
        public string InheritClassName { get; set; } = ProgramConstant.BaseClassName;
        /// <summary>
        /// 操作结果描述
        /// </summary>
        public string StrResult { get; set; }
        /// <summary>
        /// 表代码
        /// </summary>
        public string TableCord { get; set; }
        /// <summary>
        /// 服务
        /// </summary>
        public string TableServerCord { get; set; }
        /// <summary>
        /// 数据访问
        /// </summary>
        public string TableDalCord { get; set; }
        /// <summary>
        /// 类名后缀
        /// </summary>
        public string Suffix { get; set; }
        /// <summary>
        /// 是否删除旧表
        /// </summary>
        public bool IsDelectTable { get; set; }
        /// <summary>
        /// 是否添加基础数据
        /// </summary>
        public bool IsAddBaseData { get; set; } = false;

        /// <summary>
        /// 不操作
        /// </summary>
        public string DontCreate {  get; set; }

        /// <summary>
        /// 字段
        /// </summary>
        public List<FieldProperties> Fields { get; set; }
        /// <summary>
        /// 基础字段
        /// </summary>
        public List<FieldProperties> BaseFields { get; set; }
        /// <summary>
        /// 代码保存
        /// </summary>
        public ICommand CodeSaveCommand { get; set; }
        /// <summary>
        /// 创建数据库表
        /// </summary>
        public ICommand CreateDBTableCommand { get; set; }
        /// <summary>
        /// 创建实体代码
        /// </summary>
        public ICommand WebCreateEntityCodeCommand { get; set; }
        /// <summary>
        /// 创建业务代码
        /// </summary>
        public ICommand WebCreateBusinessCodeCommand { get; set; }
        /// <summary>
        /// 创建代码任务
        /// </summary>
        public int CreateCodeTaskFlag = 0;

        public TableProperties()
        {
            WebCreateBusinessCodeCommand = new RelayCommand<UiData>(WebCreateBusinessCode);
            CodeSaveCommand = new RelayCommand<string>(CodeSave);
            CreateDBTableCommand = new RelayCommand(CreateDBTable);
            WebCreateEntityCodeCommand = new RelayCommand<UiData>(WebCreateAppCode);
            var config = FileDataClass.Get<Config>();
            Suffix = config.Suffix;

            BaseFields = new List<FieldProperties>();
            BaseFields.Add(new FieldProperties() { PropertiesType = "bigint", PropertiesName = "Id", Description = "主键Id", IsIdentity = true, Primarykey = true,CanNull=false });
            BaseFields.Add(new FieldProperties() { PropertiesType = "datetime", PropertiesName = "CreateTime", Description = "创建时间" });
            BaseFields.Add(new FieldProperties() { PropertiesType = "datetime", PropertiesName = "UpdateTime", Description = "更新时间" });
            BaseFields.Add(new FieldProperties() { PropertiesType = "bigint", PropertiesName = "CreateUserId", Description = "创建者Id" });
            BaseFields.Add(new FieldProperties() { PropertiesType = "varchar", PropertiesName = "CreateUserName", Description = "创建者姓名" });
            BaseFields.Add(new FieldProperties() { PropertiesType = "bigint", PropertiesName = "UpdateUserId", Description = "修改者Id" });
            BaseFields.Add(new FieldProperties() { PropertiesType = "varchar", PropertiesName = "UpdateUserName", Description = "修改者姓名" });
            BaseFields.Add(new FieldProperties() { PropertiesType = "bit", PropertiesName = "IsDelete", Description = "软删除" });

        }

        private void WebCreateBusinessCode(UiData? data)
        {
            CreateCodeTaskFlag = 1;
            if (data == null)
            {
                return;
            }
            string result = "";
            result += "请求添加业务生成数据";
            int taskover = 0;
            data.webRequest.CreateBusinessCode(data, this, new Action<bool>((callback) =>
            {
                result += callback ? "请求成功" : "请求失败";
                taskover = 1;
            }));
            CreateCodeTaskFlag = 2;
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    if (taskover == 0)
                    {
                        Thread.Sleep(1000);
                    }
                    if (taskover==1)
                    {
                        result += " 请求生成业务代码";
                        taskover = 2;
                        data.webRequest.RunLocalBusName(data, this, new Action<bool>((callback) =>
                        {
                            result += callback ? "请求成功" : "请求失败";
                            taskover = 3;
                        }));
                        CreateCodeTaskFlag = 3;
                    }
                    if(taskover==3)
                    {
                        StrResult = result;
                        CreateCodeTaskFlag = 4;
                        break;
                    }
                }
            });
        }

        /// <summary>
        /// 创建业务代码
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void WebCreateAppCode(UiData con)
        {
            if (con == null)
            {
                return;
            }
            con.webRequest.CreateTableCode(con.config, ClassName + Suffix, TableName, new Action<bool>((callback) =>
            {
                StrResult = callback ? "请求成功" : "请求失败";
            }));
        }

        /// <summary>
        /// 创建表
        /// </summary>
        private void CreateDBTable()
        {
            var config = FileDataClass.Get<Config>();
            DatabaseHelp dbhelp = new DatabaseHelp(config);
            if (IsDelectTable)
            {
                dbhelp.DeleteTable(TableName);
            }
            else
            {
                StrResult = "表没有创建";
                return;
            }
            Func<List<SqlSugarcColsInfoMode>> func = new Func<List<SqlSugarcColsInfoMode>>(GetCols);
            dbhelp.CreateClass(TableName, TableDescribe, ClassName, func);
            StrResult = "表创建完成";
        }
        /// <summary>
        /// 获取字段
        /// </summary>
        /// <returns></returns>
        private List<SqlSugarcColsInfoMode> GetCols()
        {
            List<SqlSugarcColsInfoMode> dst = new List<SqlSugarcColsInfoMode>();

            void Add(List<FieldProperties> fild,bool isdelid)
            {
                foreach (var item in fild)
                {
                    if (IsAddBaseData&& isdelid)
                    {
                        if (item.PropertiesName.ToLower() == "id")
                        {
                            continue;
                        }
                    }
                    SqlSugarcColsInfoMode mode = new SqlSugarcColsInfoMode();
                    mode.column = new SqlSugar.SugarColumn();
                    mode.column.IsPrimaryKey = item.Primarykey;
                    mode.column.ColumnDescription = item.Description;
                    mode.column.ColumnName = item.PropertiesName;
                    mode.column.IsNullable = item.CanNull;
                    mode.column.IsIdentity = item.IsIdentity;
                    // mode.column.Length = item.Lenght;
                    mode.propertyName = item.PropertiesName;
                    mode.properyType = ToType(item.PropertiesType.Trim().ToLower());
                    dst.Add(mode);
                }
            }
            if (IsAddBaseData)
            {

                Add(BaseFields,false);
            }
            Add(Fields,true);

            return dst;
        }
        private Type ToType(string type)
        {
            switch (type)
            {
                case "varchar":
                case "nvarchar":
                case "char":
                    return typeof(string);
                case "float":
                    return typeof(Single);
                case "bit":
                    return typeof(bool);
                case "bigint": return typeof(long);
                case "int": return typeof(Int32);
                case "datetime": return typeof(DateTime?);
                default:
                    return null;
            }
        }
        private void CodeSave(string path)
        {
            var config = FileDataClass.Get<Config>();
            TableCord = CreateTableCode(config);
            TableServerCord = CreateTableServerCode(config);
            TableDalCord = CreateTableDalCode(config);
            StrResult = "代码生成完成";
            path += "\\"+ClassName+"\\";
            string filename = path + "\\" + ClassName + Suffix + ".cs";
            string filenameserver = path + "\\" + ClassName + "Service" + ".cs";
            string filenamedal = path + "\\" + ClassName + "Dal" + ".cs";
            FileSave(filename, path, TableCord);
            FileSave(filenameserver, path, TableServerCord);
            FileSave(filenamedal, path, TableDalCord);
            StrResult = "保存成功";
        }
        private void FileSave(string filename, string path, string value)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            if (File.Exists(filename))
            {
                if (IsDelectTable)
                {
                    File.Delete(filename);
                }
                else
                {
                    StrResult = "未保存 没有删除旧表退出";
                    return;
                }
            }

            File.Create(filename).Close();
            File.WriteAllText(filename, value);
        }

        private void CodeCreate(Config con)
        {
            
        }

        private string CreateTableDalCode(Config con)
        {
            string code = "";
            if (Fields == null || Fields.Count == 0)
            {
                return "";
            }
            string dalclassname = ClassName + "Dal";
            code += string.Format("namespace {0};\r\n", con.Namespace + ".Dal");
            code += string.Format("/// <summary>\r\n");
            code += string.Format("/// {0}\r\n", TableDescribe + "数据访问");
            code += string.Format("/// </summary>\r\n");
            code += string.Format("public class {0}\r\n", dalclassname);
            code += CreateLine("{");
            code += CreateLine($"public SqlSugarClient sqlSugarClient{{ get; set; }}");
            code += CreateLine("    public {0}()", dalclassname);
            code += CreateLine("   {");
            code += CreateLine("        sqlSugarClient = DBHelp.GetConnectionConfig();");
            code += CreateLine("   }");

            code += CreateLine("    public {0}(SqlSugarClient sqlSugarClient)", dalclassname);
            code += CreateLine("   {");
            code += CreateLine("        this.sqlSugarClient = sqlSugarClient;");
            code += CreateLine("   }");

            code += CreateLine("}");
            return code;
        }

        private string CreateTableServerCode(Config con)
        {
            string code = "";
            if (Fields == null || Fields.Count == 0)
            {
                return "";
            }
            string dalclassname = ClassName + "Service";
            code += string.Format("using {0}.Dal;\r\n", con.Namespace);
            code += string.Format("using {0}.Const;\r\n", con.Namespace);
            code += string.Format("namespace {0};\r\n", con.Namespace+ ".Service");
            code += string.Format("/// <summary>\r\n");
            code += string.Format("/// {0}\r\n", TableDescribe + "服务");
            code += string.Format("/// </summary>\r\n");
            code += string.Format("[ApiDescriptionSettings(BaseDBConst.GroupName, Order = 100)]\r\n");
            code += string.Format("public class {0}:  IDynamicApiController, ITransient\r\n", dalclassname);
            code += CreateLine("{");
            code += CreateLine("public {0} _sql;", ClassName+"Dal");
            code += CreateLine("    public {0}()", dalclassname);
            code += CreateLine("   {");
            code += CreateLine("        _sql=new();");
            code += CreateLine("   }");


            code += CreateLine("}");
            return code;
        }
        /// <summary>
        /// 创建表代码
        /// </summary>
        /// <param name="con"></param>
        /// <returns></returns>
        private string CreateTableCode(Config con)
        {
            string code = "";
            if (Fields == null || Fields.Count == 0)
            {
                return "";
            }
            code += string.Format("namespace {0};\r\n", con.Namespace+ ".Entity");
            code += string.Format("/// <summary>\r\n");
            code += string.Format("/// {0}\r\n", TableDescribe);
            code += string.Format("/// </summary>\r\n");
            code += string.Format("[SugarTable(\"{0}\", \"{1}\")]\r\n", TableName, TableDescribe);
            code += string.Format("[Tenant(\"{0}\")]\r\n", con.ConfigId);
            if (IsAddBaseData)
            {
                code += string.Format("public class {0} : {1}\r\n", ClassName + Suffix, InheritClassName);
            }
            else
            {
                code += string.Format("public class {0}\r\n", ClassName + Suffix);
            }
            code += CreateLine("{");

            FieldsAddToCode(Fields, ref code);
            if (IsAddBaseData)
            {
                FieldsAddToCode(BaseFields, ref code);
            }
            code += CreateLine("}");
            return code;
        }
        private void FieldsAddToCode(List<FieldProperties> fields, ref string code)
        {
            foreach (var field in fields)
            {
                if (IsAddBaseData)
                {
                    //基础数据中有ID 所以过滤掉文档中的id
                    if (field.PropertiesName == "ID")
                    {
                        continue;
                    }
                }
                code += CreateLine("    /// <summary>");
                code += CreateLine("    /// {0}", field.Description);
                code += CreateLine("    /// </summary>");
                if (field.CanNull == false)
                {
                    //code += CreateLine("    [Required]");
                }
                string iskey = field.Primarykey ? "true" : "false";
                string Identity = field.IsIdentity ? "true" : "false";
                int lenght = 0;
                string type = field.PropertiesType.Trim().ToLower();
                if (type == "varchar" || type == "nvarchar" || type == "char")
                {
                    lenght = field.Lenght;
                }
                if (type == "float")
                {
                    lenght = 53;
                }
                if (type == "bit")
                {
                    lenght = 1;
                }
                code += CreateLine("    [SugarColumn(ColumnDescription = \"{0}\", IsPrimaryKey = {1},IsIdentity = {2}, Length = {3})]", field.Description, iskey, Identity, lenght.ToString());
                code += CreateLine("    public " + ToCType(type) + " " + field.PropertiesName + " { get; set; }");
                code += CreateLine("");
            }
        }
        private string ToCType(string type)
        {
            switch (type)
            {
                case "varchar":
                case "nvarchar":
                case "char":
                    return nameof(String);
                case "float":
                    return nameof(Single);
                case "bit":
                    return nameof(Boolean);
                case "bigint": return "long";
                case "datetime": return nameof(DateTime);
                default:
                    return type;
            }
        }
        private string CreateLine(string line, params object[] strings)
        {
            if (strings == null || strings.Length == 0)
            {
                return line + "\r\n";
            }
            return string.Format(line + "\r\n", strings);
        }
    }
}
